package com.cyt.sys.service.impl;

import cn.hutool.core.util.StrUtil;
import com.cyt.base.model.dto.ReturnResult;
import com.cyt.base.util.DictCode;
import com.cyt.sys.dao.SysMenuDao;
import com.cyt.sys.model.dto.BaseMenuDto;
import com.cyt.sys.model.po.SysMenu;
import com.cyt.sys.model.po.SysUser;
import com.cyt.sys.model.vo.SysMenuVo;
import com.cyt.sys.service.SysMenuService;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;

/**
 * 基础部分-菜单service实现类
 *
 * @author shengQiang yu
 * @date 2019-04-23 11:20
 */
@Service("baseMenuService")
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenu> implements SysMenuService {

    @Resource
    private SysMenuDao sysMenuDao;

    @Autowired
    public void setBaseDao(SysMenuDao sysMenuDao) {
        this.baseDao = sysMenuDao;
    }

    /**
     * list查询
     *
     * @param sysMenuVo 参数传入对象
     * @return ReturnResult
     * @author rong yuan
     * @date 2018-11-29 15:43
     */
    @Override
    public List<SysMenu> list(SysMenuVo sysMenuVo) {
        Example example = new Example(SysMenu.class);
        example.setOrderByClause(" sort desc, create_time desc");
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(sysMenuVo.getParentId())) {
            criteria.andEqualTo("parentId", sysMenuVo.getParentId());
        }
        if (StringUtils.isNotBlank(sysMenuVo.getMenuName())) {
            criteria.andLike("menuName", "%" + sysMenuVo.getMenuName() + "%");
        }
        if (StringUtils.isNotBlank(sysMenuVo.getMenuType())) {
            criteria.andIn("menuType", Arrays.asList(sysMenuVo.getMenuType().split(",")));
        }
        criteria.andEqualTo("removeTag", DictCode.BASE_REMOVE_TAG_NORMAL);
        return sysMenuDao.selectByExample(example);
    }

    /**
     * 保存/更新菜单
     *
     * @param sysMenuVo   对象
     * @param currentUser 当前用户
     * @return ReturnResult 对象
     * @author liufu zhu
     * @date 2018-11-29 15:43
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ReturnResult addOrUpdate(SysMenuVo sysMenuVo, SysUser currentUser) {
        if (StringUtils.isBlank(sysMenuVo.getId())) {
            SysMenu sysMenu = new SysMenu(currentUser);
            sysMenu.setParentId(sysMenuVo.getParentId());
            sysMenu.setMenuName(sysMenuVo.getMenuName());
            sysMenu.setMenuType(sysMenuVo.getMenuType());
            sysMenu.setMenuUrl(sysMenuVo.getMenuUrl());
            sysMenu.setMenuIcon(sysMenuVo.getMenuIcon());
            sysMenu.setMenuGrade(initMenuGrade(sysMenuVo.getParentId()));
            sysMenu.setPermission(sysMenuVo.getPermission());
            sysMenu.setSort(sysMenuVo.getSort());
            sysMenuDao.insert(sysMenu);
        } else {
            SysMenu sysMenu = sysMenuDao.selectByPrimaryKey(sysMenuVo.getId());
            sysMenu.setParentId(sysMenuVo.getParentId());
            sysMenu.setMenuName(sysMenuVo.getMenuName());
            sysMenu.setMenuType(sysMenuVo.getMenuType());
            sysMenu.setMenuUrl(sysMenuVo.getMenuUrl());
            sysMenu.setMenuIcon(sysMenuVo.getMenuIcon());
            sysMenu.setMenuGrade(initMenuGrade(sysMenuVo.getParentId()));
            sysMenu.setPermission(sysMenuVo.getPermission());
            sysMenu.setSort(sysMenuVo.getSort());
            sysMenu.setUpdateTime(new Date());
            sysMenu.setUpdateUser(currentUser.getId());
            sysMenuDao.updateByPrimaryKey(sysMenu);
            syncUpdateChildMenu(sysMenu.getId(), sysMenu.getMenuGrade());
        }
        return new ReturnResult();
    }

    private void syncUpdateChildMenu(String id, Integer menuGrade) {
        SysMenuVo sysMenuVo = new SysMenuVo();
        sysMenuVo.setParentId(id);
        List<SysMenu> sysMenuList = this.list(sysMenuVo);
        if (CollectionUtils.isNotEmpty(sysMenuList)) {
            for (SysMenu sysMenu : sysMenuList) {
                sysMenu.setMenuGrade(menuGrade + 1);
                sysMenuDao.updateByPrimaryKey(sysMenu);
                syncUpdateChildMenu(sysMenu.getId(), sysMenu.getMenuGrade());
            }
        }
    }

    private Integer initMenuGrade(String parentId) {
        if (StringUtils.isBlank(parentId)) {
            return 1;
        } else {
            SysMenu parentMenu = sysMenuDao.selectByPrimaryKey(parentId);
            return parentMenu.getMenuGrade() + 1;
        }
    }

    /**
     * 逻辑删除菜单信息
     *
     * @param sysMenuVo 参数传入对象
     * @param sysUser   当前用户
     * @return ReturnResult
     * @author rong yuan
     * @date 2018-11-29 15:43
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ReturnResult remove(SysMenuVo sysMenuVo, SysUser sysUser) {
        //更新字段
        SysMenu sysMenu = new SysMenu();
        sysMenu.setRemoveTag(DictCode.BASE_REMOVE_TAG_DELETE);
        sysMenu.setUpdateUser(sysUser.getId());
        sysMenu.setUpdateTime(new Date());
        //筛选条件
        Example example = new Example(SysMenu.class);
        Example.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotBlank(sysMenuVo.getId())) {
            criteria.andIn("id", Arrays.asList(sysMenuVo.getId().split(",")));
        }
        return new ReturnResult(sysMenuDao.updateByExampleSelective(sysMenu, example));
    }

    /**
     * 通过角色获取菜单
     *
     * @param menuType    菜单类型
     * @param currentUser 当前用户
     * @return ReturnResult 对象
     * @author shengQiang yu
     * @date 2019-04-23 16:34
     */
    @Override
    public ReturnResult selectByRoleId(String menuType, SysUser currentUser) {
        //获取当前角色菜单（只需要目录和菜单类型）
        List<SysMenu> listRole = sysMenuDao.selectByEntity(new SysMenu(menuType, currentUser.getId()));

        List<SysMenu> oneList = new ArrayList<>();
        List<SysMenu> twoList = new ArrayList<>();
        List<SysMenu> threeList = new ArrayList<>();
        //菜单先分类
        for (SysMenu sysMenu : listRole) {
            if (DictCode.MENU_GRADE_ONE == sysMenu.getMenuGrade()) {
                oneList.add(sysMenu);
            } else if (DictCode.MENU_GRADE_TWO == sysMenu.getMenuGrade()) {
                twoList.add(sysMenu);
            } else if (DictCode.MENU_GRADE_THREE == sysMenu.getMenuGrade()) {
                threeList.add(sysMenu);
            }
        }
        //第一级
        List<BaseMenuDto> reslutList = new ArrayList<>();
        if (oneList.size() > 0) {
            for (SysMenu sysMenu : oneList) {
                BaseMenuDto baseMenuDto = BaseMenuDtoCopy(sysMenu);
                if (DictCode.MENU_TYPE_CATALOG.equals(baseMenuDto.getMenuType())) {
                    //当为目录时判断是否还有下一级
                    if (twoList.size() > 0) {
                        //第二级
                        List<BaseMenuDto> baseMenuTwoList = acceptBaseMenuDto(twoList, sysMenu.getId());
                        if (baseMenuTwoList != null && baseMenuTwoList.size() > 0) {
                            for (BaseMenuDto baseMenuTwoDto : baseMenuTwoList) {
                                if (DictCode.MENU_TYPE_CATALOG.equals(baseMenuTwoDto.getMenuType())) {
                                    //当为目录时判断是否还有下一级
                                    if (twoList.size() > 0) {
                                        //第三级
                                        List<BaseMenuDto> baseMenuThreeList = acceptBaseMenuDto(threeList, baseMenuTwoDto.getId());
                                        baseMenuTwoDto.setChildList(baseMenuThreeList);
                                    }
                                }
                            }
                        }
                        baseMenuDto.setChildList(baseMenuTwoList);
                    }
                }
                reslutList.add(baseMenuDto);
            }
        }
        return new ReturnResult(reslutList);
    }

    /**
     * 获取菜单树
     *
     * @param sysMenuVo 对象
     * @return ReturnResult 对象
     * @author shengQiang yu
     * @date 2019-04-23 16:34
     */
    @Override
    public ReturnResult dTreeList(SysMenuVo sysMenuVo) {
        List<Map<String, Object>> dtreeEntityList = new ArrayList<>();
        List<SysMenu> listAll = this.list(sysMenuVo);
        for (SysMenu sysMenu : listAll) {
            Map<String, Object> dtreeEntity = new HashedMap();
            dtreeEntity.put("id", sysMenu.getId());
            dtreeEntity.put("title", sysMenu.getMenuName());
            dtreeEntity.put("parentId", StrUtil.isEmpty(sysMenu.getParentId()) ? "0" : sysMenu.getParentId());
            dtreeEntity.put("isLast", isLast(listAll, sysMenu.getId()));
            Map<String, String> m = new HashedMap();
            m.put("type", "0");
            m.put("isChecked", "0");
            List<Map<String, String>> dtreeCheckEntityList = new ArrayList<>();
            dtreeCheckEntityList.add(m);
            dtreeEntity.put("checkArr", dtreeCheckEntityList);
            dtreeEntityList.add(dtreeEntity);
        }
        return new ReturnResult(dtreeEntityList);
    }

    /**
     * 获取子类菜单
     *
     * @author YuShengQiang
     * @date 2018-11-30 15:17
     */
    private List<BaseMenuDto> acceptBaseMenuDto(List<SysMenu> list, String parentId) {
        List<BaseMenuDto> resultList = new ArrayList<>();
        for (SysMenu sysMenu : list) {
            if (parentId.equals(sysMenu.getParentId())) {
                resultList.add(BaseMenuDtoCopy(sysMenu));
            }
        }
        return resultList;
    }

    /**
     * 菜单Vo类复制到菜单Dto
     *
     * @author YuShengQiang
     * @date 2018-11-30 15:17
     */
    private BaseMenuDto BaseMenuDtoCopy(SysMenu sysMenu) {
        BaseMenuDto baseMenuDto = new BaseMenuDto();
        try {
            BeanUtils.copyProperties(baseMenuDto, sysMenu);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return baseMenuDto;
    }

    /**
     * 判断当时对象是否有子对象
     *
     * @author YuShengQiang
     * @date 2018-12-05 17:44
     */
    private boolean isLast(List<SysMenu> list, String id) {
        if (list != null && list.size() > 0 && StringUtils.isNotBlank(id)) {
            for (SysMenu sysMenu : list) {
                if (id.equals(sysMenu.getParentId())) {
                    return false;
                }
            }
        }
        return true;
    }
}